package net.oschina.j2cache;

import net.oschina.j2cache.ehcache.EhCacheClient;
import net.oschina.j2cache.ehcache.EhCacheProvider;
import net.oschina.j2cache.redis.RedisCacheProvider;
import net.oschina.j2cache.redis.client.RedisClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
import java.util.function.Consumer;
import java.util.function.Function;

/**
 * 缓存入口
 *
 * @author winterlau
 */
public class J2Cache {

    private final static Logger log = LoggerFactory.getLogger(J2Cache.class);

    private final static String CONFIG_FILE = "/j2cache.properties";
    private final static CacheChannel channel;
    private final static Properties config;

    static {
        try {
            config = loadConfig();
            String cache_broadcast = config.getProperty("cache.broadcast");
            if ("redis".equalsIgnoreCase(cache_broadcast))
                channel = RedisCacheChannel.getInstance();
            else if ("jgroups".equalsIgnoreCase(cache_broadcast))
                channel = JGroupsCacheChannel.getInstance();
            else
                throw new CacheException("Cache Channel not defined. name = " + cache_broadcast);
        } catch (IOException e) {
            throw new CacheException("Unable to load j2cache configuration " + CONFIG_FILE, e);
        }
    }

    public static CacheChannel getChannel() {
        return channel;
    }

    ///**
    // * 提供直接操作redis的底层client，直接操作L1/L2缓存请使用CacheManager
    // * 注意：需要自行调用RedisClient.close()释放资源
    // *
    // * @return
    // */
    //public static RedisClient getRedisClient() {
    //    return RedisCacheProvider.getInstance().getUnderlyingClient();
    //}

    public static <T> T callWithRedis(Function<RedisClient, T> callback) {
        return RedisCacheProvider.getInstance().getResource().call(callback);
    }

    public static void runWithRedis(Consumer<RedisClient> consumer) {
        RedisCacheProvider.getInstance().getResource().run(consumer);
    }

    /**
     * 提供直接操作ehcache的底层client，直接操作L1/L2缓存请使用CacheManager
     *
     * @return
     */
    public static EhCacheClient getEhCacheClient() {
        return EhCacheProvider.getInstance().getUnderlyingClient();
    }

    public static Properties getConfig() {
        return config;
    }

    /**
     * 加载配置
     *
     * @return
     * @throws IOException
     */
    private static Properties loadConfig() throws IOException {
        log.info("Load J2Cache Config File : [{}].", CONFIG_FILE);
        InputStream configStream = J2Cache.class.getClassLoader().getParent().getResourceAsStream(CONFIG_FILE);
        if (configStream == null)
            configStream = CacheManager.class.getResourceAsStream(CONFIG_FILE);
        if (configStream == null)
            throw new CacheException("Cannot find " + CONFIG_FILE + " !!!");

        Properties props = new Properties();

        try {
            props.load(configStream);
        } finally {
            configStream.close();
        }

        return props;
    }

}
